﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UpdateSourceBindingAction.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the UpdateSourceBindingAction type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Windows.Data
{
    using System.Diagnostics;
    using System.Reflection;
    using System.Windows;
    using System.Windows.Interactivity;

    public class UpdateSourceBindingAction : TriggerAction<FrameworkElement>
    {
        public static readonly DependencyProperty TargetPropertyNameProperty = DependencyProperty.Register("TargetPropertyName",
            typeof(string), typeof(UpdateSourceBindingAction), new PropertyMetadata(TargetPropertyNameChanged));

        private static void TargetPropertyNameChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var updateSourceBinding = obj as UpdateSourceBindingAction;
            if (updateSourceBinding != null)
            {
                updateSourceBinding.UpdateTargetProperty();
            }
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            UpdateTargetProperty();
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            TargetProperty = null;
        }

        private void UpdateTargetProperty()
        {
            if (AssociatedObject == null || string.IsNullOrEmpty(TargetPropertyName))
            {
                TargetProperty = null;
            }
            else
            {
                var propertyField = AssociatedObject.GetType().GetField(TargetPropertyName + "Property", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
                if (propertyField == null || !typeof(DependencyProperty).IsAssignableFrom(propertyField.FieldType))
                {
                    Debug.WriteLine("Unable to find dependency property '{0}' on type '{1}'.", TargetPropertyName, AssociatedObject.GetType().FullName);
                }
                else
                {
                    TargetProperty = propertyField.GetValue(null) as DependencyProperty;
                }
            }
        }

        public string TargetPropertyName
        {
            get { return (string)GetValue(TargetPropertyNameProperty); }
            set { SetValue(TargetPropertyNameProperty, value); }
        }

        protected DependencyProperty TargetProperty { get; private set; }

        protected override void Invoke(object parameter)
        {
            if (TargetProperty != null)
            {
                var bindingExpression = AssociatedObject.GetBindingExpression(TargetProperty);
                if (bindingExpression != null)
                {
                    bindingExpression.UpdateSource();
                }
            }
        }
    }
}
